home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / application / TimerQueue.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  6.0 KB  |  227 lines  |  [TEXT/CWIE]

  1. // TimerQueue.java
  2. // By Ned Etcode
  3. // Copyright 1996, 1997 Netscape Communications Corp.  All rights reserved.
  4.  
  5. package netscape.application;
  6.  
  7. import netscape.util.*;
  8.  
  9. /** Private class to manage a queue of Timers. The Timers are chained
  10.   * together in a linked list sorted by the order in which they will expire.
  11.   * @note 1.0 changes to detect and stop dealocking better
  12.   */
  13. class TimerQueue implements Runnable, ApplicationObserver  {
  14.     Timer firstTimer;
  15.     boolean running;
  16.  
  17.     public TimerQueue() {
  18.         super();
  19.  
  20.         Application application  = Application.application();
  21.  
  22.         application.addObserver(this);
  23.         if (application.isRunning()) {
  24.             start();
  25.         }
  26.     }
  27.  
  28.     synchronized void start() {
  29.         if (running) {
  30.             throw new InconsistencyException("Can't start a TimerQueue that is already running");
  31.         } else {
  32.             Thread timerThread = new Thread(this, "TimerQueue");
  33.  
  34.             try {
  35.                 if( timerThread.getPriority() > Thread.MIN_PRIORITY )
  36.                    timerThread.setPriority(timerThread.getPriority() - 1);
  37.  
  38.                 timerThread.setDaemon(true);
  39.             } catch (SecurityException e) {
  40.             }
  41.             timerThread.start();
  42.             running = true;
  43.         }
  44.     }
  45.  
  46.     synchronized void stop() {
  47.         running = false;
  48.         notify();
  49.     }
  50.  
  51.     synchronized void addTimer(Timer timer, long expirationTime) {
  52.         Timer previousTimer, nextTimer;
  53.  
  54.         // If the Timer is already in the queue, then ignore the add.
  55.  
  56.         if (timer.running)
  57.             return;
  58.  
  59.         previousTimer = null;
  60.         nextTimer = firstTimer;
  61.  
  62.         // Insert the Timer into the linked list in the order they will
  63.         // expire.  If two timers expire at the same time, put the newer entry
  64.         // later so they expire in the order they came in.
  65.  
  66.         while (nextTimer != null) {
  67.             if (nextTimer.expirationTime > expirationTime)
  68.                 break;
  69.  
  70.             previousTimer = nextTimer;
  71.             nextTimer = nextTimer.nextTimer;
  72.         }
  73.  
  74.         if (previousTimer == null)
  75.             firstTimer = timer;
  76.         else
  77.             previousTimer.nextTimer = timer;
  78.  
  79.         timer.expirationTime = expirationTime;
  80.         timer.nextTimer = nextTimer;
  81.         timer.running = true;
  82.  
  83.         notify();
  84.     }
  85.  
  86.     synchronized void removeTimer(Timer timer) {
  87.         boolean found;
  88.         Timer previousTimer, nextTimer;
  89.  
  90.         if (!timer.running)
  91.             return;
  92.  
  93.         previousTimer = null;
  94.         nextTimer = firstTimer;
  95.         found = false;
  96.  
  97.         while (nextTimer != null) {
  98.             if (nextTimer == timer) {
  99.                 found = true;
  100.                 break;
  101.             }
  102.  
  103.             previousTimer = nextTimer;
  104.             nextTimer = nextTimer.nextTimer;
  105.         }
  106.  
  107.         if (!found)
  108.             return;
  109.  
  110.         if (previousTimer == null)
  111.             firstTimer = timer.nextTimer;
  112.         else
  113.             previousTimer.nextTimer = timer.nextTimer;
  114.  
  115.         timer.expirationTime = 0;
  116.         timer.nextTimer = null;
  117.         timer.running = false;
  118.     }
  119.  
  120.     synchronized boolean containsTimer(Timer timer) {
  121.         return timer.running;
  122.     }
  123.  
  124.     // If there are a ton of timers, this method may never return.  It loops
  125.     // checking to see if the head of the Timer list has expired.  If it has,
  126.     // it posts the Timer and reschedules it if necessary.
  127.  
  128.     synchronized long postExpiredTimers() {
  129.         long currentTime, timeToWait;
  130.         Timer timer;
  131.  
  132.         // The timeToWait we return should never be negative and only be zero
  133.         // when we have no Timers to wait for.
  134.  
  135.         do {
  136.             timer = firstTimer;
  137.             if (timer == null)
  138.                 return 0;
  139.  
  140.             currentTime = System.currentTimeMillis();
  141.             timeToWait = timer.expirationTime - currentTime;
  142.  
  143.             if (timeToWait <= 0) {
  144.                 timer.post(currentTime);
  145.                 removeTimer(timer);
  146.  
  147.                 // This tries to keep the interval uniform at the cost of
  148.                 // drift.
  149.  
  150.                 if (timer.repeats())
  151.                     addTimer(timer, currentTime + timer.delay());
  152.  
  153.                 // Allow other threads to call addTimer() and removeTimer()
  154.                 // even when we are posting Timers like mad.  Since the wait()
  155.                 // releases the lock, be sure not to maintain any state
  156.                 // between iterations of the loop.
  157.  
  158.                 try {
  159.                     wait(1);
  160.                 } catch (InterruptedException e) {
  161.                 }
  162.             }
  163.         } while (timeToWait <= 0);
  164.  
  165.         return timeToWait;
  166.     }
  167.  
  168.     public synchronized void run() {
  169.         long timeToWait;
  170.  
  171.         while (running) {
  172.             timeToWait = postExpiredTimers();
  173.             try {
  174.                 wait(timeToWait);
  175.             } catch (InterruptedException e) {
  176.             }
  177.         }
  178.     }
  179.  
  180.     public synchronized String toString() {
  181.         StringBuffer buf;
  182.         Timer nextTimer;
  183.  
  184.         buf = new StringBuffer();
  185.         buf.append("TimerQueue (");
  186.  
  187.         nextTimer = firstTimer;
  188.         while (nextTimer != null) {
  189.             buf.append(nextTimer.toString());
  190.  
  191.             nextTimer = nextTimer.nextTimer;
  192.             if (nextTimer != null)
  193.                 buf.append(", ");
  194.         }
  195.  
  196.         buf.append(")");
  197.         return buf.toString();
  198.     }
  199.  
  200.     /*
  201.      * Informs the observer that the application's focused view has changed.
  202.      */
  203.     public void focusDidChange(Application application,View focusedView) {
  204.     }
  205.  
  206.     /*
  207.      * Informs the observer that the application's current document window
  208.      * has changed.
  209.      */
  210.     public void currentDocumentDidChange(Application application,Window document) {
  211.     }
  212.  
  213.     public void applicationDidPause(Application app) {
  214.     }
  215.  
  216.     public  void applicationDidResume(Application app) {
  217.     }
  218.  
  219.     public synchronized void applicationDidStart(Application app) {
  220.         start();
  221.     }
  222.  
  223.     public synchronized void applicationDidStop(Application app) {
  224.         stop();
  225.     }
  226. }
  227.